package com.alibaba.japan.club.runtime.springmvc.servlet.view.freemarker;

import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.log4j.Logger;
import org.springframework.context.i18n.LocaleContext;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import com.alibaba.japan.club.runtime.springmvc.module.ModuleHelper;
import com.alibaba.japan.club.runtime.springmvc.module.ModulePattern;

import freemarker.template.Configuration;
import freemarker.template.Template;

/**
 * screen类的调用类
 * 
 * @author:shaochuan.wangsc
 * @date:2009-3-24
 * 
 */
public class FreeMarkerScreenResolver {

	private static final Logger logger = Logger.getLogger(FreeMarkerScreenResolver.class);

	private FreeMarkerConfigurer freemarkerConfigurer;

	private ModulePattern modulePattern;

	public void setFreemarkerConfigurer(FreeMarkerConfigurer freemarkerConfigurer) {
		this.freemarkerConfigurer = freemarkerConfigurer;
	}

	public void setModulePattern(ModulePattern modulePattern) {
		this.modulePattern = modulePattern;
	}

	/**
	 * 获得系统中已注册的screen类名
	 * 
	 * @param file
	 * @return
	 */
	private FreeMarkerScreen getScreenBean(String file) {
		String screenBeanName = ModuleHelper.getScreenBeanName(file);
		FreeMarkerScreen freeMarkerScreen = null;
		freeMarkerScreen = (FreeMarkerScreen) (modulePattern.getScreenMapping().get(screenBeanName));
		if (freeMarkerScreen == null) {
			if (logger.isDebugEnabled()) {
				logger.debug("There is no FreeMarkerScreen(" + screenBeanName + ") for : " + file);
			}
		}
		return freeMarkerScreen;
	}

	/**
	 * 将freeMarkerRootModel放入到当前的model中
	 * 
	 * @param model
	 * @param freeMarkerRootModel
	 */
	private void putFreeMarkerRootModel(Map<String, Object> model, Map<String, Object> freeMarkerRootModel) {
		for (Entry<String, Object> element : freeMarkerRootModel.entrySet()) {
			String key = element.getKey();
			Object value = element.getValue();
			if (model.get(key) == null) {
				model.put(key, value);
			} else {
				throw new RuntimeException("Cannot expose model attribute '" + key
						+ "' because of an existing model object of the same name");
			}
		}
	}

	/**
	 * 渲染screen
	 * 
	 * @param freemarkerRootModel
	 * @param screenBean
	 * @param file
	 * @return
	 */
	private String renderScreen(Map<String, Object> freeMarkerRootModel, FreeMarkerScreen screenBean, String file)
			throws Exception {
		Map<String, Object> model = new HashMap<String, Object>();

		Configuration configuration = freemarkerConfigurer.getConfiguration();
		StringWriter writer = new StringWriter();
		Template template = null;
		LocaleContext localeContext = LocaleContextHolder.getLocaleContext();

		if (screenBean != null) {
			screenBean.referenceData(model);
		}
		putFreeMarkerRootModel(model, freeMarkerRootModel);
		template = configuration.getTemplate(file, localeContext.getLocale());
		template.process(model, writer);
		return writer.toString();
	}

	/**
	 * 设置screen
	 * 
	 * @param req
	 * @param root
	 * @param file
	 */
	public String setTemplate(Map<String, Object> freemarkerRootModel, String file) {
		// 如果传入的字符串为null或是空串,则返回空字符串
		String screen = "";
		if (file == null || "".equals((file = file.trim()))) {
			return screen;
		}
		// 开始执行screen类
		FreeMarkerScreen screenBean = null;
		try {
			screenBean = getScreenBean(file);
			screen = renderScreen(freemarkerRootModel, screenBean, file);
		} catch (Exception exception) {
			throw new RuntimeException("Cannot setTemplate(" + file + "), because of an exception occurred", exception);
		}
		return screen;
	}
}
